import logging
from datetime import datetime
from django.db import transaction
from common.merchant.models import Role, RoleLevel
from common.utils.db import list_object, get_object
from common.permission.handler import create_page_block_field
from common.utils.maestro_exceptions import (
    MaestroException,
    ILLEGAL_PARAMETER,
    ACCESS_DENIED
)
from common.user.models import User

_LOGGER = logging.getLogger(__name__)


def get_role(query_dct):
    return get_object(query_dct, Role)


def list_role(query_dct):
    return list_object(query_dct, Role)


def create_role(role_name, desc, merchant_id, supervisor_id, perm):
    supervisor = Role.objects.filter(id=supervisor_id).first()
    if supervisor.role_level != RoleLevel.ROOT.value:
        if not supervisor or supervisor.merchant_id != merchant_id:
            raise MaestroException(ILLEGAL_PARAMETER, '上级主管不存在')
    if supervisor.role_level in [RoleLevel.WORKER.value, RoleLevel.NOVICE.value]:
        raise MaestroException(ACCESS_DENIED)
    perm_to_set = ',' + ','.join(perm.keys()) + ','
    with transaction.atomic():
        role = Role(
            role_name=role_name,
            desc=desc,
            merchant_id=merchant_id,
            supervisor_id=supervisor_id,
            role_level=supervisor.role_level + 1,
            perm=perm_to_set,
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow()
        )
        role.save()
        create_page_block_field(role_id=role.id, perm=perm)
    return role


def update_role(merchant_id, admin_role_level, role_id, role_name, desc, supervisor_id, perm):
    role = Role.objects.filter(id=role_id).first()
    if not role:
        raise MaestroException(ILLEGAL_PARAMETER, '角色不存在')
    if role.role_name != role_name and Role.objects.filter(role_name=role_name,
                                                           merchant_id=merchant_id).count() > 0:
        raise MaestroException(ILLEGAL_PARAMETER, '角色名重复')
    if role.supervisor_id != supervisor_id and not admin_role_level['is_root']:
        raise MaestroException(ACCESS_DENIED)
    supervisor = Role.objects.filter(id=supervisor_id).first()
    perm_to_set = ',' + ','.join(perm.keys()) + ','
    if supervisor.role_level != RoleLevel.ROOT.value:
        if supervisor.merchant_id != role.merchant_id:
            raise MaestroException(ILLEGAL_PARAMETER, '非法操作')
        supervisor_perm_list = supervisor.perm.split(',')[1:-1]
        for perm_id, block_key_list in perm.items():
            if perm_id not in supervisor_perm_list:
                raise MaestroException(ILLEGAL_PARAMETER, '权限不得大于上级')
    with transaction.atomic():
        create_page_block_field(role_id=role_id, perm=perm)
        role.role_name = role_name
        role.role_level = supervisor.role_level + 1
        role.desc = desc
        role.supervisor_id = supervisor_id
        role.perm = perm_to_set
        role.save()
    return {}


def delete_role(merchant_id, user_role_level, role_id):
    role = Role.objects.filter(id=role_id).first()
    if not role:
        raise MaestroException(ILLEGAL_PARAMETER, '角色不存在')
    if role_id == user_role_level[merchant_id]['role_id']:
        raise MaestroException(ACCESS_DENIED)
    if role.supervisor_id != user_role_level[merchant_id]['role_id'] and not user_role_level['is_root']:
        raise MaestroException(ACCESS_DENIED)
    children_role = Role.objects.filter(supervisor_id=role_id).all()
    with transaction.atomic():
        delete_role_db(role_id)
        for children in children_role:
            delete_role_db(children.id)
    return {}


def delete_role_db(role_id):
    users = User.objects.filter(role__contains="," + str(role_id) + ",").all()
    for user in users:
        user_role_list = user.role.strip(",").split(",")
        user_role_list.remove(str(role_id))
        user.role = ',' + ','.join(user_role_list) + ',' if len(user_role_list) > 0 else ""
        user.save()
    Role.objects.filter(id=role_id).delete()


def get_user_merchant_role(merchant_id, user_role):
    user_role_list = [int(role_id) for role_id in user_role.split(',')[1:-1]]
    role = get_role({'id__in': user_role_list, 'merchant_id': merchant_id})
    return role.__dict__ if role else dict()
